<!DOCTYPE html>
<html>
<head>
    <title>Cycloid Diagram</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #f0f0f0;
        }
        canvas {
            border: 1px solid #ccc;
            background-color: #fff;
        }
    </style>
</head>
<body>
    <canvas id="physicsCanvas" width="800" height="550"></canvas>
    <script>
        const canvas = document.getElementById('physicsCanvas');
        const ctx = canvas.getContext('2d');

        // --- Configuration ---
        const R = 100; // Radius of the circle
        const theta = 1.7; // Angle for the general position in radians
        const origin = { x: canvas.width / 2, y: 420 };

        // --- Helper Functions ---
        function drawArrow(x1, y1, x2, y2, color = 'black', lw = 1.5) {
            ctx.save();
            ctx.strokeStyle = color;
            ctx.fillStyle = color;
            ctx.lineWidth = lw;
            const headlen = 10;
            const angle = Math.atan2(y2 - y1, x2 - x1);

            // Draw line
            ctx.beginPath();
            ctx.moveTo(x1, y1);
            ctx.lineTo(x2, y2);
            ctx.stroke();

            // Draw arrowhead
            ctx.beginPath();
            ctx.moveTo(x2, y2);
            ctx.lineTo(x2 - headlen * Math.cos(angle - Math.PI / 6), y2 - headlen * Math.sin(angle - Math.PI / 6));
            ctx.lineTo(x2 - headlen * Math.cos(angle + Math.PI / 6), y2 - headlen * Math.sin(angle + Math.PI / 6));
            ctx.closePath();
            ctx.fill();
            ctx.restore();
        }
        
        function drawText(text, x, y, size = 20, font = "serif", color = "black") {
            ctx.fillStyle = color;
            ctx.font = `${size}px ${font}`;
            ctx.fillText(text, x, y);
        }

        // --- Main Drawing Logic ---
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        // 1. Draw Coordinate System
        drawArrow(50, origin.y, canvas.width - 50, origin.y); // x-axis
        drawArrow(origin.x, canvas.height - 50, origin.x, 20); // y-axis
        drawText("O", origin.x - 20, origin.y + 20);
        drawText("x", canvas.width - 40, origin.y - 10, 22, 'italic');
        drawText("y", origin.x + 10, 35, 22, 'italic');

        // 2. Draw Cycloid Curve: x=R(t+sint), y=R(1-cost)
        ctx.beginPath();
        ctx.strokeStyle = 'black';
        ctx.lineWidth = 2;
        for (let t = -Math.PI; t <= Math.PI; t += 0.01) {
            const x = origin.x + R * (t + Math.sin(t));
            const y = origin.y - R * (1 - Math.cos(t));
            if (t === -Math.PI) {
                ctx.moveTo(x, y);
            } else {
                ctx.lineTo(x, y);
            }
        }
        ctx.stroke();

        // 3. Draw Track MN
        const y_MN = origin.y - 2 * R;
        const x_M = origin.x - Math.PI * R;
        const x_N = origin.x + Math.PI * R;
        ctx.beginPath();
        ctx.moveTo(x_M - 40, y_MN);
        ctx.lineTo(x_N + 40, y_MN);
        ctx.stroke();
        
        // Labels for MN
        drawText("M", x_M - 30, y_MN - 10, 22, 'italic');
        drawText("N", x_N + 15, y_MN - 10, 22, 'italic');
        ctx.beginPath();
        ctx.arc(x_M, y_MN, 3, 0, 2 * Math.PI);
        ctx.fill();
        ctx.beginPath();
        ctx.arc(x_N, y_MN, 3, 0, 2 * Math.PI);
        ctx.fill();
        drawText("-πR", x_M - 45, y_MN - 25, 20);
        drawText("πR", x_N - 10, y_MN - 25, 20);
        
        // 4. Draw Initial (Dashed) Circle
        const c0 = { x: origin.x, y: origin.y - R };
        ctx.beginPath();
        ctx.setLineDash([5, 5]);
        ctx.arc(c0.x, c0.y, R, 0, 2 * Math.PI);
        ctx.stroke();
        ctx.setLineDash([]);
        drawText("C", c0.x - 8, c0.y + 8, 22, 'italic');
        drawText("P", origin.x + 10, origin.y - 10, 22, 'italic');
        
        // 5. Draw General Position Circle (Solid)
        const c = { x: origin.x + R * theta, y: origin.y - R };
        ctx.beginPath();
        ctx.lineWidth = 2;
        ctx.arc(c.x, c.y, R, 0, 2 * Math.PI);
        ctx.stroke();
        ctx.lineWidth = 1;
        drawText("C", c.x - 8, c.y + 8, 22, 'italic');
        
        // 6. Draw Points A, Q, P and related vectors for general position
        const A = {
            x: origin.x + R * (theta + Math.sin(theta)),
            y: origin.y - R * (1 - Math.cos(theta))
        };
        const Q = { x: c.x, y: y_MN };

        // Point markers
        ctx.beginPath();
        ctx.arc(A.x, A.y, 4, 0, 2 * Math.PI);
        ctx.fill();
        ctx.beginPath();
        ctx.arc(Q.x, Q.y, 4, 0, 2 * Math.PI);
        ctx.fill();

        // Labels
        drawText("A(x, y)", A.x + 15, A.y + 25, 20, 'italic');
        drawText("Q", Q.x - 20, Q.y - 10, 22, 'italic');
        drawText("P", A.x - 25, A.y - 5, 22, 'italic');

        // Vectors CP and QP
        drawArrow(c.x, c.y, A.x, A.y);
        drawArrow(Q.x, Q.y, A.x, A.y);

        // Angle theta
        ctx.beginPath();
        ctx.setLineDash([2, 3]);
        ctx.moveTo(c.x, c.y);
        ctx.lineTo(c.x, A.y);
        ctx.stroke();
        ctx.setLineDash([]);
        
        ctx.beginPath();
        ctx.arc(c.x, c.y, 30, Math.PI / 2, Math.PI / 2 + theta); // arc for theta
        ctx.stroke();
        const angle_label_pos = {
            x: c.x + 38 * Math.cos(Math.PI / 2 + theta / 2),
            y: c.y + 38 * Math.sin(Math.PI / 2 + theta / 2)
        };
        drawText("θ", angle_label_pos.x, angle_label_pos.y + 5, 20, 'italic');

        // 7. Draw the Tangent Line (Corrected)
        // The tangent vector is perpendicular to QP vector.
        // QP = (A.x - Q.x, A.y - Q.y)
        // Tangent vector is proportional to (-(A.y - Q.y), A.x - Q.x)
        const tangent_vec = {
            dx: -(A.y - Q.y),
            dy: A.x - Q.x
        };
        const norm = Math.sqrt(tangent_vec.dx**2 + tangent_vec.dy**2);
        const tangent_dir = { dx: tangent_vec.dx / norm, dy: tangent_vec.dy / norm };
        
        const tangent_start = { x: A.x - tangent_dir.dx * 15, y: A.y - tangent_dir.dy * 15 };
        const tangent_end = { x: A.x + tangent_dir.dx * 80, y: A.y + tangent_dir.dy * 80 };

        drawArrow(tangent_start.x, tangent_start.y, tangent_end.x, tangent_end.y, 'black', 2);
        drawText("切线", tangent_end.x - 70, tangent_end.y - 15, 20);

        // 8. Caption
        drawText("图 1", canvas.width / 2 - 25, canvas.height - 15, 20);

    </script>
</body>
</html>